#pragma once

#include <cstdint>
#include <cstring>

#include <vector>
#include <functional>

#include "r_socket_proxy_def.h"

namespace eniac
{

class r_socket_proxy
{
public:
    using receiving_message_callback_t = std::function<void(int32_t socket_id, std::vector<uint8_t>& message)>;

private:
    r_socket_proxy();
    r_socket_proxy(const r_socket_proxy&) = delete;
    r_socket_proxy(r_socket_proxy&&) = delete;
    r_socket_proxy& operator=(const r_socket_proxy&) = delete;
    r_socket_proxy& operator=(r_socket_proxy&&) = delete;

public:
    ~r_socket_proxy();

    static r_socket_proxy* get_instance();
    r_socket_proxy_ret_t start();
    void stop();
    int32_t create_socket(r_socket_type type);
    void destory_socket(int32_t socket_id);
    r_socket_proxy_ret_t start_socket(int32_t socket_id);
    void stop_socket(int32_t socket_id);
    r_socket_proxy_ret_t send_message(int32_t socket_id, const std::vector<uint8_t>& message);
    void set_callback_of_receiving_message(const receiving_message_callback_t& callback);
    r_socket_proxy_ret_t set_socket_property(int32_t socket_id, r_socket_property_type type, void* property, size_t property_size);

private:
    void start_process_thread();
    void stop_process_thread();
    void start_callback_thread();
    void stop_callback_thread();

    void process_thread_function();
    void callback_thread_function();
    void close_sockets_all();
};

}